package com.hushan.elevator.controller;


import cn.hutool.core.bean.BeanUtil;
import com.hushan.elevator.dto.PageInfoDto;
import com.hushan.elevator.dto.RiskRecordDto;
import com.hushan.elevator.model.*;
import com.hushan.elevator.security.SecurityUtils;
import com.hushan.elevator.service.*;
import com.hushan.elevator.utils.MinioUtils;
import com.hushan.elevator.utils.Result;
import com.hushan.elevator.utils.ResultCode;
import com.hushan.elevator.vo.HandleRiskVo;
import com.hushan.elevator.vo.RiskRecordDetailVo;
import com.hushan.elevator.vo.RiskSearchVo;
import com.hushan.elevator.vo.RiskTableVo;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;


@RestController
@RequestMapping("/risks")
public class RiskController {
    private final RiskRecordService riskService;
    private final RiskInfoService riskInfoService;
    private final DeptService deptService;
    private final MntPersonService mntPersonService;
    private final DeviceInfoService deviceInfoService;
    private final UserService userService;
    @Value("${spring.minio.bucket.deviceImg}")
    private String deviceImg;
    @Value("${spring.minio.bucket.riskImg}")
    private String riskBucket;
    @Resource
    private MinioUtils minioUtils;

    public RiskController(RiskRecordService riskService, RiskInfoService riskInfoService, DeptService deptService, MntPersonService mntPersonService, DeviceInfoService deviceInfoService, UserService userService) {
        this.riskService = riskService;
        this.riskInfoService = riskInfoService;
        this.deptService = deptService;
        this.mntPersonService = mntPersonService;
        this.deviceInfoService = deviceInfoService;
        this.userService = userService;
    }


    @Operation(summary = "获取全部风险记录", description = "获取本系统全部风险记录,RiskSearchVo进行搜索查询")
    @GetMapping("/record")
    public Result getRisks(@ModelAttribute RiskSearchVo searchVo,
                           @PageableDefault(size = 10, sort = "created_time", direction = Sort.Direction.DESC) Pageable pageable) {

        User user = SecurityUtils.getUser();

        if(searchVo.getDeptId() == null) {
            searchVo.setDeptId(deptService.findDeptByUserId(user.getUserId()).getDeptId());
        }

        boolean permission = deptService.findUserPermissionForDept(user, searchVo.getDeptId());
        if (!permission) {
            return Result.FAIL();
        }

        Page<Object[]> page = riskService.findRisk(searchVo,pageable);

        List<RiskRecordDto> recordDtos = riskService.convertRiskRecordDto(page.stream().toList());

        List<RiskTableVo> rst = new ArrayList<>();
        for (RiskRecordDto dto : recordDtos) {
            User deviceManager = userService.findUserByUserId(dto.getDeviceManager());
            RiskTableVo riskTableVo = new RiskTableVo();
            riskTableVo.setManageName(deviceManager.getTitle());
            riskTableVo.setManagementId(deviceManager.getUserId());
            BeanUtil.copyProperties(dto, riskTableVo);
            rst.add(riskTableVo);
        }
        return new Result(ResultCode.SUCCESS, new PageInfoDto(page.getTotalPages(), page.getSize(), pageable.getPageNumber(), page.getTotalElements()), rst);
    }

    @Operation(summary = "根据ID获取风险详细内容", description = "根据指定的风险ID返回单个风险信息的详细信息")
    @GetMapping("/record/{id}")
    public Result getRiskById(@PathVariable("id") int id) {
        RiskRecordDto riskRecordDetail = riskService.findRiskRecordDetail(id);
        if (riskRecordDetail == null) {
            return Result.FAIL();
        }

        RiskRecordDetailVo rst = new RiskRecordDetailVo();
        BeanUtil.copyProperties(riskRecordDetail, rst);

        // the device mnt person
//        MntPerson mntPerson = mntPersonService.findByDevice(riskRecordDetail.getDeviceId());
        // the device manager
        User deviceManager = userService.findUserByUserId(riskRecordDetail.getDeviceManager());
        // the Device Type
        DeviceType deviceType = deviceInfoService.findTypeById(riskRecordDetail.getDeviceId());
        // the status at the time of risk record
        RiskRecordElevStatus status = riskService.findElevStatus(id);

//        if (mntPerson != null) {
//            rst.setMntPersonName(mntPerson.getName());
//            rst.setMntPersonId(mntPerson.getMntUserId());
//        }

        if (deviceManager != null) {
            rst.setManageName(deviceManager.getTitle());
            rst.setManagementId(deviceManager.getUserId());
            rst.setManageMobile(deviceManager.getTelNumb());
        }

        if (deviceType != null) {
            rst.setDeviceType(deviceType.getTitle());
            rst.setDeviceTypeId(deviceType.getTypeId());
        }
        if (status != null) {
            BeanUtil.copyProperties(status, rst);
        }

        return new Result(ResultCode.SUCCESS, rst);
    }



    @Operation(summary = "关注风险记录", description = "根据提供的ID和关注方案更新风险记录的信息")
    @PutMapping("/record/star/{id}")
    public Result updateRisk(@PathVariable("id") int id, @RequestParam("value") Boolean value) {
        RiskRecord recordById = riskService.findRiskRecordById(id);
        if (recordById == null) {
            return Result.FAIL();
        }
        User user = SecurityUtils.getUser();
        DeviceInfo deviceInfo = deviceInfoService.findBySerialNumb(recordById.getDeviceSerial());
        boolean permission = deptService.findUserPermissionForDept(user, deviceInfo.getDeptId());
        System.out.println(permission);
        if (!permission) {
            return Result.UN_AUTHORISE();
        }
        recordById.setIsStar(value ? 1 : 0);
        riskService.updateRiskRecord(recordById);
        return new Result(ResultCode.SUCCESS);
    }

    @Operation(summary = "处理风险", description = "处理风险信息")
    @PutMapping("/record/handle")
    public Result handleRisks(@RequestBody HandleRiskVo handleInfo) {
        User requester = SecurityUtils.getUser();
        int[] list = handleInfo.getList();
        for (int i : list) {
            DeviceInfo device = riskService.findDeviceByRisk(i);
            boolean permission = deptService.findUserPermissionForDept(requester, device.getDeptId());
            if (!permission) return Result.UN_AUTHORISE();
        }
        for (int i : list) {
            RiskRecord record = riskService.findRiskRecordById(i);
            record.setState(1);
            record.setFinishedTime(LocalDateTime.now());
            riskService.updateRiskRecord(record);
            riskService.addHandleInfo(i, requester.getUserId(), handleInfo.getHandleType(), handleInfo.getInfo());
        }
        return new Result(ResultCode.SUCCESS);
    }

    // 删除风险信息
    @Operation(summary = "删除风险信息", description = "根据指定的风险ID删除对应的风险信息")
    @DeleteMapping("/{id}")
    public Result deleteRisk(@PathVariable("id") int id) {
        try {
            riskService.deleteRiskRecord(id);
            return new Result(ResultCode.SUCCESS);
        } catch (Exception e) {
            return new Result(ResultCode.FAIL);
        }
    }

    @Operation(summary = "获取设备的全部风险信息", description = "获取设备的全部风险信息")
    @GetMapping("/record/device/{id}")
    public Result getRisksByDeviceId(@PathVariable("id") int id,@PageableDefault(size = 10, sort = "created_time", direction = Sort.Direction.DESC) Pageable pageable) {
        boolean permission = deviceInfoService.detectAuthorize(id);
        if (!permission) return Result.UN_AUTHORISE();
        DeviceInfo deviceInfo = deviceInfoService.findById(id);
        RiskSearchVo searchVo = new RiskSearchVo();
        searchVo.setDeviceSerialNumber(deviceInfo.getSerialNumber());
        Page<Object[]> page = riskService.findRisk(searchVo, pageable);
        List<RiskRecordDto> records = riskService.convertRiskRecordDto(page.stream().toList());

        List<RiskTableVo> rst = new ArrayList<>();
        for (RiskRecordDto dto : records) {
            // the device mnt person
//            MntPerson mntPerson = mntPersonService.findByDevice(id);
            // the device manager
            User deviceManager = userService.findUserByUserId(deviceInfo.getCreatedBy());
            RiskTableVo riskTableVo = new RiskTableVo();
//            riskTableVo.setMntPersonName(mntPerson.getName());
            riskTableVo.setManageName(deviceManager.getTitle());
//            riskTableVo.setMntPersonId(mntPerson.getMntUserId());
            riskTableVo.setManagementId(deviceManager.getUserId());
            BeanUtil.copyProperties(dto, riskTableVo);
            rst.add(riskTableVo);
        }
        return new Result(ResultCode.SUCCESS, new PageInfoDto(page.getTotalPages(), page.getSize(), pageable.getPageNumber(), page.getTotalElements()), rst);
    }

    @Operation(summary = "根据ID获取风险发生时的照片",
            description = "根据ID获取风险发生时的照片")
    @RequestMapping(value = "/record/device/img/{id}", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
    public byte[] getRiskImgById(@PathVariable("id") int id) {
        RiskRecord record = riskService.findRiskRecordById(id);
        String eventId = record.getEventId();
        ResponseEntity<byte[]> download = minioUtils.download(record.getDeviceSerial() + '/' + eventId + ".jpg", riskBucket);
        if (download == null) return null;
        return download.getBody();
    }

    @Operation(summary = "获取某设备的最新风险抓拍照片",
            description = "获取某设备的最新风险抓拍照片")
    @RequestMapping(value = "/record/device/{id}/img", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
    public byte[] getLatestRiskImgByDevice(@PathVariable("id") int id) {
        RiskRecord record = riskService.findLatestRecordByDevice(id);
        // has none risk record
        if (record == null) return null;
        String eventId = record.getEventId();
        ResponseEntity<byte[]> download = minioUtils.download(record.getDeviceSerial() + '/' + eventId + ".jpg", riskBucket);
        if (download == null) return null;
        return download.getBody();
    }

    @Operation(summary = "获取某设备的最新风险信息",
            description = "获取某设备的最新风险信息")
    @RequestMapping(value = "/record/device/{id}/info", method = RequestMethod.GET)
    public Result getLatestRiskInfoByDevice(@PathVariable("id") int id) {
        RiskRecord record = riskService.findLatestRecordByDevice(id);
        // has none risk record
        if (record == null) return null;
        RiskInfo riskInfo = riskInfoService.findBySerialNumber(record.getSerialNumber());
        RiskRecordDto dto = new RiskRecordDto();
        BeanUtil.copyProperties(record, dto);
        BeanUtil.copyProperties(riskInfo, dto);
        return new Result(ResultCode.SUCCESS, dto);
    }
}
